/**
 * @fileoverview Tests for no-useless-computed-key rule.
 * @author Burak Yigit Kaya
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const rule = require("../../../lib/rules/no-useless-computed-key"),
	RuleTester = require("../../../lib/rule-tester/rule-tester");

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester({ languageOptions: { ecmaVersion: 2022 } });

ruleTester.run("no-useless-computed-key", rule, {
	valid: [
		"({ 'a': 0, b(){} })",
		"({ [x]: 0 });",
		"({ a: 0, [b](){} })",
		"({ ['__proto__']: [] })",
		"var { 'a': foo } = obj",
		"var { [a]: b } = obj;",
		"var { a } = obj;",
		"var { a: a } = obj;",
		"var { a: b } = obj;",
		{
			code: "class Foo { a() {} }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "class Foo { 'a'() {} }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "class Foo { [x]() {} }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "class Foo { ['constructor']() {} }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "class Foo { static ['prototype']() {} }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "(class { 'a'() {} })",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "(class { [x]() {} })",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "(class { ['constructor']() {} })",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "(class { static ['prototype']() {} })",
			options: [{ enforceForClassMembers: true }],
		},
		"class Foo { 'x'() {} }",
		"(class { [x]() {} })",
		"class Foo { static constructor() {} }",
		"class Foo { prototype() {} }",
		{
			code: "class Foo { ['x']() {} }",
			options: [{ enforceForClassMembers: false }],
		},
		{
			code: "(class { ['x']() {} })",
			options: [{ enforceForClassMembers: false }],
		},
		{
			code: "class Foo { static ['constructor']() {} }",
			options: [{ enforceForClassMembers: false }],
		},
		{
			code: "class Foo { ['prototype']() {} }",
			options: [{ enforceForClassMembers: false }],
		},
		{
			code: "class Foo { a }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "class Foo { ['constructor'] }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "class Foo { static ['constructor'] }",
			options: [{ enforceForClassMembers: true }],
		},
		{
			code: "class Foo { static ['prototype'] }",
			options: [{ enforceForClassMembers: true }],
		},

		/*
		 * Well-known browsers throw syntax error bigint literals on property names,
		 * so, this rule doesn't touch those for now.
		 */
		{
			code: "({ [99999999999999999n]: 0 })",
			languageOptions: { ecmaVersion: 2020 },
		},
	],
	invalid: [
		{
			code: "({ ['0']: 0 })",
			output: "({ '0': 0 })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'0'" },
				},
			],
		},
		{
			code: "var { ['0']: a } = obj",
			output: "var { '0': a } = obj",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'0'" },
				},
			],
		},
		{
			code: "({ ['0+1,234']: 0 })",
			output: "({ '0+1,234': 0 })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'0+1,234'" },
				},
			],
		},
		{
			code: "({ [0]: 0 })",
			output: "({ 0: 0 })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "0" },
				},
			],
		},
		{
			code: "var { [0]: a } = obj",
			output: "var { 0: a } = obj",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "0" },
				},
			],
		},
		{
			code: "({ ['x']: 0 })",
			output: "({ 'x': 0 })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "var { ['x']: a } = obj",
			output: "var { 'x': a } = obj",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "var { ['__proto__']: a } = obj",
			output: "var { '__proto__': a } = obj",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'__proto__'" },
				},
			],
		},
		{
			code: "({ ['x']() {} })",
			output: "({ 'x'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "({ [/* this comment prevents a fix */ 'x']: 0 })",
			output: null,
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "({ ['x' /* this comment also prevents a fix */]: 0 })",
			output: null,
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "({ [('x')]: 0 })",
			output: "({ 'x': 0 })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "var { [('x')]: a } = obj",
			output: "var { 'x': a } = obj",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "({ *['x']() {} })",
			output: "({ *'x'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "({ async ['x']() {} })",
			output: "({ async 'x'() {} })",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "({ get[.2]() {} })",
			output: "({ get.2() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: ".2" },
				},
			],
		},
		{
			code: "({ set[.2](value) {} })",
			output: "({ set.2(value) {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: ".2" },
				},
			],
		},
		{
			code: "({ async[.2]() {} })",
			output: "({ async.2() {} })",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: ".2" },
				},
			],
		},
		{
			code: "({ [2]() {} })",
			output: "({ 2() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ get [2]() {} })",
			output: "({ get 2() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ set [2](value) {} })",
			output: "({ set 2(value) {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ async [2]() {} })",
			output: "({ async 2() {} })",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ get[2]() {} })",
			output: "({ get 2() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ set[2](value) {} })",
			output: "({ set 2(value) {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ async[2]() {} })",
			output: "({ async 2() {} })",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ get['foo']() {} })",
			output: "({ get'foo'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'foo'" },
				},
			],
		},
		{
			code: "({ *[2]() {} })",
			output: "({ *2() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ async*[2]() {} })",
			output: "({ async*2() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "({ ['constructor']: 1 })",
			output: "({ 'constructor': 1 })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'constructor'" },
				},
			],
		},
		{
			code: "({ ['prototype']: 1 })",
			output: "({ 'prototype': 1 })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'prototype'" },
				},
			],
		},
		{
			code: "class Foo { ['0']() {} }",
			output: "class Foo { '0'() {} }",
			options: [{ enforceForClassMembers: true }],
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'0'" },
				},
			],
		},
		{
			code: "class Foo { ['0+1,234']() {} }",
			output: "class Foo { '0+1,234'() {} }",
			options: [{}],
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'0+1,234'" },
				},
			],
		},
		{
			code: "class Foo { ['x']() {} }",
			output: "class Foo { 'x'() {} }",
			options: [{ enforceForClassMembers: void 0 }],
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "class Foo { [/* this comment prevents a fix */ 'x']() {} }",
			output: null,
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "class Foo { ['x' /* this comment also prevents a fix */]() {} }",
			output: null,
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "class Foo { [('x')]() {} }",
			output: "class Foo { 'x'() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "class Foo { *['x']() {} }",
			output: "class Foo { *'x'() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "class Foo { async ['x']() {} }",
			output: "class Foo { async 'x'() {} }",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "class Foo { get[.2]() {} }",
			output: "class Foo { get.2() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: ".2" },
				},
			],
		},
		{
			code: "class Foo { set[.2](value) {} }",
			output: "class Foo { set.2(value) {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: ".2" },
				},
			],
		},
		{
			code: "class Foo { async[.2]() {} }",
			output: "class Foo { async.2() {} }",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: ".2" },
				},
			],
		},
		{
			code: "class Foo { [2]() {} }",
			output: "class Foo { 2() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { get [2]() {} }",
			output: "class Foo { get 2() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { set [2](value) {} }",
			output: "class Foo { set 2(value) {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { async [2]() {} }",
			output: "class Foo { async 2() {} }",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { get[2]() {} }",
			output: "class Foo { get 2() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { set[2](value) {} }",
			output: "class Foo { set 2(value) {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { async[2]() {} }",
			output: "class Foo { async 2() {} }",
			languageOptions: { ecmaVersion: 8 },
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { get['foo']() {} }",
			output: "class Foo { get'foo'() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'foo'" },
				},
			],
		},
		{
			code: "class Foo { *[2]() {} }",
			output: "class Foo { *2() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { async*[2]() {} }",
			output: "class Foo { async*2() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "2" },
				},
			],
		},
		{
			code: "class Foo { static ['constructor']() {} }",
			output: "class Foo { static 'constructor'() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'constructor'" },
				},
			],
		},
		{
			code: "class Foo { ['prototype']() {} }",
			output: "class Foo { 'prototype'() {} }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'prototype'" },
				},
			],
		},
		{
			code: "(class { ['x']() {} })",
			output: "(class { 'x'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'x'" },
				},
			],
		},
		{
			code: "(class { ['__proto__']() {} })",
			output: "(class { '__proto__'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'__proto__'" },
				},
			],
		},
		{
			code: "(class { static ['__proto__']() {} })",
			output: "(class { static '__proto__'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'__proto__'" },
				},
			],
		},
		{
			code: "(class { static ['constructor']() {} })",
			output: "(class { static 'constructor'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'constructor'" },
				},
			],
		},
		{
			code: "(class { ['prototype']() {} })",
			output: "(class { 'prototype'() {} })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'prototype'" },
				},
			],
		},
		{
			code: "class Foo { ['0'] }",
			output: "class Foo { '0' }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'0'" },
				},
			],
		},
		{
			code: "class Foo { ['0'] = 0 }",
			output: "class Foo { '0' = 0 }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'0'" },
				},
			],
		},
		{
			code: "class Foo { static[0] }",
			output: "class Foo { static 0 }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "0" },
				},
			],
		},
		{
			code: "class Foo { ['#foo'] }",
			output: "class Foo { '#foo' }",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'#foo'" },
				},
			],
		},
		{
			code: "(class { ['__proto__'] })",
			output: "(class { '__proto__' })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'__proto__'" },
				},
			],
		},
		{
			code: "(class { static ['__proto__'] })",
			output: "(class { static '__proto__' })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'__proto__'" },
				},
			],
		},
		{
			code: "(class { ['prototype'] })",
			output: "(class { 'prototype' })",
			errors: [
				{
					messageId: "unnecessarilyComputedProperty",
					data: { property: "'prototype'" },
				},
			],
		},
	],
});
